package com.supercube.sport.yoga.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.supercube.common.utils.ShiroUtils;
import com.supercube.common.utils.StringUtils;
import com.supercube.common.utils.TimeUtils;
import com.supercube.sport.yoga.bo.BatchSigned;
import com.supercube.sport.yoga.bo.ClassSingedBo;
import com.supercube.sport.yoga.bo.MemberSignedBo;
import com.supercube.sport.yoga.dao.BookingCourseMapper;
import com.supercube.sport.yoga.dao.MemberCardBasicInfoMapper;
import com.supercube.sport.yoga.dao.MemberCardBindingInfoMapper;
import com.supercube.sport.yoga.domain.BookingCourseDTO;
import com.supercube.sport.yoga.domain.MemberCardBindingInfoDTO;
import com.supercube.sport.yoga.service.BookingCourseService;
import com.supercube.sport.yoga.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class BookingCourseServiceImpl implements BookingCourseService {

    @Autowired
    private BookingCourseMapper bookingCourseMapper;
    @Autowired
    private MemberCardBindingInfoMapper memberCardBindingInfoMapper;
    @Autowired
    private MemberCardBasicInfoMapper memberCardBasicInfoMapper;

    @Override
    public int save(BookingCourseDTO dto) {
        return bookingCourseMapper.insert(dto);
    }

    @Override
    public int update(BookingCourseDTO dto) {
        return bookingCourseMapper.updateByPrimaryKeySelective(dto);
    }

    @Override
    public BookingCourseVO queryBookingCourseById(String id) {
        return bookingCourseMapper.selectByPrimaryKey(id);
    }

    @Override
    public int savePrivateBookingCourse(BookingCourseDTO dto) {
        return bookingCourseMapper.insert(dto);
    }

    @Override
    public List<MemberBookingCourseInfoVO> queryMemberBookingCourseInfoByClassId(String classId) {
        return bookingCourseMapper.selectBookingCourseByClassTableId(classId);
    }

    /**
     * 会员卡类型
     * 储值类型	1
     * 次卡类型	2
     * 期限类型	3
     */
    public List<SignedRecordVo> getSignedRecord(SignedRecordVo vo) {
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<SignedRecordVo> list = bookingCourseMapper.getSignedRecord(vo);
        for (SignedRecordVo signed : list) {
            //计算费用
            if (Objects.equals(signed.getCardType(), "1")) {
                //储值类型
                double cost = Integer.valueOf(StringUtils.isEmpty(signed.getBookingNum()) ? "0" : signed.getBookingNum())
                        * Double.valueOf(StringUtils.isEmpty(signed.getSellPrice()) ? "0.0" : signed.getSellPrice());
                signed.setCost(cost == 0 ? "" : (cost + "元"));
            } else {
                //期限类型、次卡类型
                signed.setCost(StringUtils.isEmpty(signed.getBookingNum()) ? "" : (signed.getBookingNum() + "次"));
            }
        }
        return list;
    }

    public List<Map<String, String>> queryVenue(String memberId) {
        Long userId = ShiroUtils.getUserId();
        return bookingCourseMapper.queryVenue(userId, memberId);
    }

    public List<MemberCardBindVo> getMemberCardAppointment(Map<String, String> map) {
        return bookingCourseMapper.getMemberCardAppointment(map);
    }

    public List<MemberCardBindVo> getMemberCard(Map<String, String> map) {
        return bookingCourseMapper.getMemberCard(map);
    }

    public List<CourseBasicInfoVO> getCourseBaseInfo(Map<String,String> map){
        return bookingCourseMapper.getCourseBaseInfo(map);
    }
    public List<ClassInfoVo> getClassInfo(ClassSingedBo bo) {
        return bookingCourseMapper.getClassInfo(bo);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveMemberSigned(MemberSignedBo bo) {
        /**
         * 会员预约签到：
         * 1、如果是根据课程类型（团课、小班、私教）且会员卡是次卡，则绑卡表中对应的剩余 团课、小班私教 的次数 减去 预约人数。
         * 2、如果预约的卡 是储值卡 则对应的剩余金额 减去 该节课程售价*预约人数。
         * 3、如果预约的卡是期限卡 ，不扣费
         */
        bo.getBookingCourseId().forEach(id->{
            String memberId = bo.getMemberId();
            String bookingCourseId = id;
            MemberSigned(memberId, bookingCourseId);

        });
        Long userId = ShiroUtils.getUserId();
        //更新签到状态和备注
        bo.getBookingCourseId().forEach(id -> {
            BookingCourseDTO dto = new BookingCourseDTO();
            dto.setStatus("3");//正常签到	3
            dto.setZb(bo.getZb());
            dto.setId(id);
            dto.setSignInTime(TimeUtils.getCurrentTime());
            dto.setSignInUser(userId.toString());
            bookingCourseMapper.updateByPrimaryKeySelective(dto);
        });

    }

    private void MemberSigned(String memberId, String bookingCourseId) {
        ClassSingedBo bo = new ClassSingedBo();
        bo.setMemberId(memberId);
        bo.setBookingCourseId(bookingCourseId);
        bo.setSignStatus("1");//未签到
        List<ClassInfoVo> vo = bookingCourseMapper.getClassInfo(bo);
        ClassInfoVo classInfoVo = vo.get(0);
        log.info("签到课程信息：" + JSONObject.toJSONString(classInfoVo));
        // 扣费
        MemberCardBindingInfoDTO bind = memberCardBindingInfoMapper.selectByCardIdAndMemberId(classInfoVo.getCardId(), memberId);
        log.info("签到前绑卡信息：" + JSONObject.toJSONString(bind));
        //查询会员卡类型
        MemberCardBasicInfoVO card = memberCardBasicInfoMapper.selectByPrimaryKey(classInfoVo.getCardId());
        log.info("签到会员卡信息：" + JSONObject.toJSONString(card));
        if (Objects.equals(card.getCardType(), "2")) {
            log.info("次卡--签到");
            //次卡 默认都为 1
            int cost = 1 * Integer.parseInt(classInfoVo.getBookingNum());
            log.info("次卡--签到人数："+cost);
            if (Objects.equals(classInfoVo.getCourseType(), "1")) {
                log.info("次卡--签到--大团课");
                //大团课
                //判断是否存在赠送的
                if (StringUtils.isNotBlank(bind.getNumberGroupLessonsPresent()) && Integer.parseInt(bind.getNumberGroupLessonsPresent()) > 0) {
                    if (Integer.parseInt(bind.getNumberGroupLessonsPresent()) >= cost) {
                        log.info("次卡--签到--大团课赠送扣除次数："+cost);
                        bind.setNumberGroupLessonsPresent(Integer.parseInt(bind.getNumberGroupLessonsPresent()) - cost + "");
                    } else {
                        // 先扣除赠送的
                        bind.setNumberGroupLessonsPresent("0");
                        int surplus = cost - Integer.parseInt(bind.getNumberGroupLessonsPresent());
                        log.info("次卡--签到--大团课赠送扣除次数："+bind.getNumberGroupLessonsPresent());
                        log.info("次卡--签到--大团课余额扣除次数："+surplus);
                        bind.setNumberGroupLessons(Integer.parseInt(bind.getNumberGroupLessons()) - surplus + "");
                    }
                } else {
                    log.info("次卡--签到--大团课余额扣除次数："+cost);
                    bind.setNumberGroupLessons(Integer.parseInt(bind.getNumberGroupLessons()) - cost + "");
                }
            } else if (Objects.equals(classInfoVo.getCourseType(), "2")) {
                log.info("次卡--签到--小团课");
                //小团课
                if (StringUtils.isNotBlank(bind.getNumberSmallClassesPresent()) && Integer.parseInt(bind.getNumberSmallClassesPresent()) > 0) {
                    if (Integer.parseInt(bind.getNumberSmallClassesPresent()) >= cost) {
                        log.info("次卡--签到--小团课赠送扣除次数："+cost);
                        bind.setNumberSmallClassesPresent(Integer.parseInt(bind.getNumberSmallClassesPresent()) - cost + "");
                    } else {
                        // 先扣除赠送的
                        bind.setNumberSmallClassesPresent("0");
                        int surplus = cost - Integer.parseInt(bind.getNumberSmallClassesPresent());
                        log.info("次卡--签到--小团课赠送扣除次数："+bind.getNumberSmallClassesPresent());
                        log.info("次卡--签到--小团课余额扣除次数："+surplus);
                        bind.setNumberSmallClasses(Integer.parseInt(bind.getNumberSmallClasses()) - surplus + "");
                    }
                } else {
                    log.info("次卡--签到--小团课余额扣除次数："+cost);
                    bind.setNumberSmallClasses(Integer.parseInt(bind.getNumberSmallClasses()) - cost + "");
                }
            } else if (Objects.equals(classInfoVo.getCourseType(), "3")) {
                log.info("次卡--签到--私教课");
                //私教课
                if (StringUtils.isNotBlank(bind.getNumberPrivateTeachingPresent()) && Integer.parseInt(bind.getNumberPrivateTeachingPresent()) > 0) {
                    if (Integer.parseInt(bind.getNumberPrivateTeachingPresent()) >= cost) {
                        log.info("次卡--签到--私教课赠送扣除次数："+cost);
                        bind.setNumberPrivateTeachingPresent(Integer.parseInt(bind.getNumberPrivateTeachingPresent()) - cost + "");
                    } else {
                        // 先扣除赠送的
                        bind.setNumberPrivateTeachingPresent("0");
                        int surplus = cost - Integer.parseInt(bind.getNumberPrivateTeachingPresent());
                        log.info("次卡--签到--私教课赠送扣除次数："+bind.getNumberPrivateTeachingPresent());
                        log.info("次卡--签到--私教课余额扣除次数："+surplus);
                        bind.setNumberPrivateTeaching(Integer.parseInt(bind.getNumberPrivateTeaching()) - surplus + "");
                    }
                } else {
                    log.info("次卡--签到--私教课余额扣除次数："+cost);
                    bind.setNumberPrivateTeaching(Integer.parseInt(bind.getNumberPrivateTeaching()) - cost + "");
                }
            }
        } else if (Objects.equals(card.getCardType(), "1")) {
            log.info("储值卡--课程价格：" + classInfoVo.getCoursePrice()+ ",预约人数：" + classInfoVo.getBookingNum());
            int cost = Integer.parseInt(classInfoVo.getCoursePrice()) * Integer.parseInt(classInfoVo.getBookingNum());
            log.info("储值卡--共消费价格：" + cost);
            //储值卡
            if (StringUtils.isNotBlank(bind.getStoredValueAmountPresent()) && Integer.parseInt(bind.getStoredValueAmountPresent()) > 0) {
                //减去售价
                if (Integer.parseInt(bind.getStoredValueAmountPresent()) >= cost) {
                    log.info("储值卡--签到--私教课赠送扣除金额："+cost);
                    bind.setStoredValueAmountPresent(Integer.parseInt(bind.getStoredValueAmountPresent()) - cost + "");
                } else {
                    // 先扣除赠送的
                    bind.setStoredValueAmountPresent("0");
                    int surplus = cost - Integer.parseInt(bind.getStoredValueAmountPresent());
                    log.info("储值卡--签到--赠送扣除金额："+bind.getStoredValueAmountPresent());
                    log.info("储值卡--签到--余额扣除金额："+surplus);
                    bind.setStoredValueAmount(Integer.parseInt(bind.getStoredValueAmount()) - surplus + "");
                }
            } else {
                log.info("储值卡--签到--余额扣除金额："+cost);
                bind.setStoredValueAmount(Integer.parseInt(bind.getStoredValueAmount()) - cost + "");
            }
        } else if (Objects.equals(card.getCardType(), "1")) {
            log.info("期限卡预约签到....");
        }
        if (Objects.equals(bind.getCardOpeningTime(), "1")) {//期限卡才有
            log.info("会员卡首次开卡:", bind.getCardId(), ",会员：", bind.getMemberId());
            bind.setCardOpeningTime(TimeUtils.getCurrentTime());
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar c = Calendar.getInstance();
            log.info("预约签到日期:" + sf.format(c.getTime()));
            c.add(Calendar.DAY_OF_MONTH, Integer.parseInt(bind.getDurationDays()));
            log.info("签到后会员卡截至日期:" + sf.format(c.getTime()));
            bind.setStopCardEndTime(sf.format(c.getTime()));
        }
        memberCardBindingInfoMapper.updateByPrimaryKey(bind);
        log.info("签到后绑卡信息：" + JSONObject.toJSONString(bind));
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchSaveMemberSigned(List<BatchSigned> list) {
        /**
         * 会员预约签到：
         * 1、如果是根据课程类型（团课、小班、私教）且会员卡是次卡，则绑卡表中对应的剩余 团课、小班私教 的次数 减去 预约人数。
         * 2、如果预约的卡 是储值卡 则对应的剩余金额 减去 该节课程售价*预约人数。
         * 3、如果预约的卡是期限卡 ，不扣费
         */
        list.forEach(batchSigned->{
            String memberId = batchSigned.getMemberId();
            String bookingCourseId = batchSigned.getBookingCourseId();
            MemberSigned(memberId, bookingCourseId);

        });
        //更新签到状态和备注
        list.forEach(batchSigned -> {
            BookingCourseDTO dto = new BookingCourseDTO();
            dto.setStatus("3");//正常签到	3
            dto.setZb("批量签到");
            dto.setId(batchSigned.getBookingCourseId());
            bookingCourseMapper.updateByPrimaryKeySelective(dto);
        });

    }

    @Override
    public List<BookingCourseVO> queryBookingCourseBySiteId(String siteId, String classId) {
        return bookingCourseMapper.selectBookingCourseBySiteId(siteId, classId);
    }

    @Override
    public int countBookingCourseInfoByClassId(String classId) {
        return bookingCourseMapper.countBookingCourseInfoByClassId(classId);
    }
}
